import sys, os
import pandas as pd
import matplotlib.pyplot as plt
from PyQt5.QtCore import Qt, pyqtSignal, QObject
from PyQt5.QtGui import QIcon, QKeySequence, QColor, QBrush
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                             QHBoxLayout, QGroupBox, QPushButton, QCheckBox,
                             QRadioButton, QComboBox, QLabel, QSpinBox,
                             QDoubleSpinBox, QLineEdit, QTextEdit, QSplitter,
                             QFileDialog, QMessageBox, QAction, QToolBar, QTableWidget, QTableWidgetItem, QAbstractItemView)

# -------------------------------------------------
# 中间占位画布（后续可换成 Matplotlib / QTableView）
# -------------------------------------------------
class MiddleCanvas(QWidget):
    def __init__(self):
        super().__init__()
        self.layout = QVBoxLayout(self)
        self.info = QLabel("显示区：等待控件事件…")
        self.info.setAlignment(Qt.AlignCenter)
        self.info.setStyleSheet("background:#e0e0e0; font-size:18px;")
        self.layout.addWidget(self.info)

        # 添加 QTableWidget 用于显示表格数据
        self.table = QTableWidget()
        self.table.setVisible(False)  # 默认隐藏
        self.layout.addWidget(self.table)

    def set_text(self, txt):
        self.info.setText(txt)

    def show_table(self, df: pd.DataFrame):
        self.info.setVisible(False)
        self.table.setVisible(True)
        self.table.setRowCount(len(df))
        self.table.setColumnCount(len(df.columns))
        self.table.setHorizontalHeaderLabels(df.columns)
        self.table.setVerticalHeaderLabels(df.index.astype(str))

        for row in range(len(df)):
            for col in range(len(df.columns)):
                item = QTableWidgetItem(str(df.iloc[row, col]))
                self.table.setItem(row, col, item)

        self.table.resizeColumnsToContents()
        self.table.setAlternatingRowColors(True)

# -------------------------------------------------
# 左侧控件面板
# -------------------------------------------------
class LeftPanel(QWidget):
    data_changed = pyqtSignal(dict)  # 自定义信号，用于发送数据

    def __init__(self):
        super().__init__()
        self.build_ui()
        self.connect_events()

    def build_ui(self):
        layout = QVBoxLayout(self)
        layout.setSpacing(6)

        # 1. 按钮
        grp = QGroupBox("按钮")
        grp.setCheckable(True)
        grp.setChecked(False)
        v = QVBoxLayout(grp)
        self.btn_normal = QPushButton("普通按钮")
        self.btn_toggle = QPushButton("开关按钮")
        self.btn_toggle.setCheckable(True)
        v.addWidget(self.btn_normal)
        v.addWidget(self.btn_toggle)
        layout.addWidget(grp)

        # 2. 选择类
        grp = QGroupBox("布尔选择")
        v = QVBoxLayout(grp)
        self.chk = QCheckBox("复选框")
        self.rad1 = QRadioButton("单选1")
        self.rad2 = QRadioButton("单选2")
        self.rad1.setChecked(True)
        v.addWidget(self.chk)
        v.addWidget(self.rad1)
        v.addWidget(self.rad2)
        layout.addWidget(grp)

        # 3. 下拉框
        layout.addWidget(QLabel("下拉框"))
        self.combo = QComboBox()
        self.combo.addItems(["选项 A", "选项 B", "选项 C"])
        layout.addWidget(self.combo)

        # 4. 数字输入
        layout.addWidget(QLabel("整数 SpinBox"))
        self.spin_int = QSpinBox()
        self.spin_int.setRange(0, 99)
        layout.addWidget(self.spin_int)

        layout.addWidget(QLabel("浮点 DoubleSpinBox"))
        self.spin_float = QDoubleSpinBox()
        self.spin_float.setRange(0.0, 1.0)
        self.spin_float.setSingleStep(0.05)
        layout.addWidget(self.spin_float)

        # 5. 文字输入
        layout.addWidget(QLabel("LineEdit"))
        self.line_edit = QLineEdit("单行文字")
        layout.addWidget(self.line_edit)

        layout.addWidget(QLabel("TextEdit"))
        self.text_edit = QTextEdit("多行文字")
        layout.addWidget(self.text_edit)

        # 6. 确认按钮
        self.confirm_button = QPushButton("确认")
        self.confirm_button.clicked.connect(self.collect_and_emit)
        layout.addWidget(self.confirm_button)

        layout.addStretch()

    def connect_events(self):
        pass

    def collect_and_emit(self):
        data = {
            "toggle_button": self.btn_toggle.isChecked(),
            "checkbox": self.chk.isChecked(),
            "radio": "单选1" if self.rad1.isChecked() else "单选2",
            "combo": self.combo.currentText(),
            "int": self.spin_int.value(),
            "float": self.spin_float.value(),
            "line": self.line_edit.text(),
            "text": self.text_edit.toPlainText()
        }
        self.data_changed.emit(data)

# -------------------------------------------------
# 主窗口：菜单栏 + 工具栏 + 信号处理
# -------------------------------------------------
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5 完整模板")
        self.resize(1000, 650)

        # 中心组件
        splitter = QSplitter(Qt.Horizontal)
        self.left = LeftPanel()
        self.canvas = MiddleCanvas()
        splitter.addWidget(self.left)
        splitter.addWidget(self.canvas)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 2)
        splitter.setSizes([330, 670])
        self.setCentralWidget(splitter)

        # 信号连接
        self.left.data_changed.connect(self.show_data)

        # 创建菜单 & 工具栏
        self.create_actions()
        self.create_menu()
        self.create_toolbar()

        # 状态栏
        self.status = self.statusBar()

    def show_data(self, data):
        lines = [f"{k}: {v}" for k, v in data.items()]
        self.canvas.set_text("\n".join(lines))

    def create_actions(self):
        self.act_new = QAction("&新建", self, shortcut=QKeySequence.New,
                               triggered=lambda: self.canvas.set_text("【动作】新建"))
        self.act_open = QAction("&打开", self, shortcut=QKeySequence.Open,
                                triggered=self.open_file)
        self.act_save = QAction("&保存", self, shortcut=QKeySequence.Save,
                                triggered=self.save_file)
        self.act_exit = QAction("退出", self, shortcut="Ctrl+Q",
                                triggered=self.close)
        self.act_about = QAction("关于", self, triggered=self.about)

    def create_menu(self):
        menubar = self.menuBar()
        file_menu = menubar.addMenu("文件(&F)")
        file_menu.addAction(self.act_new)
        file_menu.addAction(self.act_open)
        file_menu.addAction(self.act_save)
        file_menu.addSeparator()
        file_menu.addAction(self.act_exit)

        help_menu = menubar.addMenu("帮助(&H)")
        help_menu.addAction(self.act_about)

    def create_toolbar(self):
        toolbar = QToolBar("工具")
        self.addToolBar(toolbar)
        toolbar.addAction(self.act_new)
        toolbar.addAction(self.act_open)
        toolbar.addAction(self.act_save)

    def open_file(self):
        path, _ = QFileDialog.getOpenFileName(
            self,
            "打开表格",     # 弹出打开文件新窗口的标题
            "",
            "Excel (*.xlsx);;CSV (*.csv);;All Files (*)"
        )
        if not path:
            return      # path为空字符串，直接return

        try:
            if path.lower().endswith(".csv"):
                df = pd.read_csv(path)
            else:
                df = pd.read_excel(path)
                df.set_index(df.columns[0], inplace=True)   # 把第一列重新设置为index
        except Exception as e:
            QMessageBox.critical(self, "读取失败", str(e))  # 捕获任何异常提示
            return

        self.canvas.show_table(df)
        self.status.showMessage(f"已加载表格文件：{os.path.basename(path)}")

    def save_file(self):
        path, _ = QFileDialog.getSaveFileName(self, "保存", os.getcwd(),
                                              "Text (*.txt);;All Files (*)")
        if path:
            self.canvas.set_text(f"【保存】{path}")

    def about(self):
        QMessageBox.about(self, "关于", "PyQt5 GUI 模板\n作者：<你的名字>")

# -------------------------------------------------
# 入口
# -------------------------------------------------
if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = MainWindow()
    win.show()
    sys.exit(app.exec_())